﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using Google.GData.Photos;

namespace PicasaWebAlbumsDownloader
{
    public sealed partial class MainForm : Form, ISupportProgress, ISupportOutput, IView
    {
        private readonly Controller controller;
        private Dictionary<PicasaEntry, int> albums;
        private bool needCancel;

        public MainForm()
        {
            InitializeComponent();
            clbAlbums.DisplayMember = "Text";
            controller = new Controller(this);
            controller.DownloadProgress += OnDownloadProgress;
        }

        #region ISupportOutput Members

        public void Clear()
        {
            tbOutput.Clear();
        }

        public void AppendLine(string text)
        {
            if (tbOutput.Text.Length > 0)
            {
                tbOutput.AppendText(string.Format("{0}{1}", Environment.NewLine, text));
            }
            else
            {
                tbOutput.AppendText(text);
            }
        }

        #endregion

        #region ISupportProgress Members

        bool ISupportProgress.Enabled
        {
            get { return pnlControls.Enabled; }
            set { pnlControls.Enabled = value; }
        }

        public bool WaitCursor
        {
            get { return Cursor == Cursors.WaitCursor; }
            set { Cursor = value ? Cursors.WaitCursor : Cursors.Default; }
        }

        public ProgressState ProgressState
        {
            get
            {
                return pbDownload.Value == pbDownload.Minimum
                           ? ProgressState.Min
                           : (pbDownload.Value == pbDownload.Maximum ? ProgressState.Max : ProgressState.Unknown);
            }
            set
            {
                pbDownload.Value = value == ProgressState.Min
                                       ? pbDownload.Minimum
                                       : (value == ProgressState.Max
                                              ? pbDownload.Maximum
                                              : (pbDownload.Maximum - pbDownload.Minimum)/2);
            }
        }

        public int ProgressValue
        {
            get { return pbDownload.Value; }
            set
            {
                pbDownload.Value = value;
                Application.DoEvents();
            }
        }

        #endregion

        #region IView Members

        public ISupportOutput Output
        {
            get { return this; }
        }

        public PicasaEntry SelectedAlbum
        {
            get
            {
                if (clbAlbums.SelectedItem == null)
                {
                    return null;
                }
                var entry = ((PicasaEntry) ((ListViewItem) clbAlbums.SelectedItem).Tag);
                return entry;
            }
        }

        public bool UseOriginalPhotoSize
        {
            get { return chkOriginalSize.Checked; }
        }

        public string AppName
        {
            get { return Text; }
        }

        public string UserName
        {
            get { return tbUser.Text; }
        }

        public string OutputDir { get; private set; }

        public Dictionary<PicasaEntry, int> SelectedAlbums
        {
            get
            {
                var result = new Dictionary<PicasaEntry, int>();
                if (albums == null)
                {
                    return result;
                }

                foreach (PicasaEntry picasaEntry in
                    from ListViewItem checkedItem in clbAlbums.CheckedItems
                    select (PicasaEntry) checkedItem.Tag)
                {
                    result.Add(picasaEntry, albums[picasaEntry]);
                }

                return result;
            }
        }

        public ISupportProgress Progress
        {
            get { return this; }
        }

        #endregion

        private void OnDownloadProgress(object sender, CancelEventArgs e)
        {
            if (needCancel)
            {
                e.Cancel = true;
                needCancel = false;
            }
        }

        private void OnGetAlbumListClick(object sender, EventArgs e)
        {
            using (new Progress(this))
            {
                clbAlbums.Items.Clear();

                albums = controller.RetrieveAlbumList();

                foreach (var album in albums)
                {
                    var item = new ListViewItem(album.Key.Title.Text + " (" + album.Value + " )")
                                   {
                                       Tag = album.Key
                                   };
                    clbAlbums.Items.Add(item);
                }

                Output.AppendLine(string.Format("{0} albums have been retrieved.", albums.Count));
            }
        }

        private void OnAlbumListSelectedIndexChanged(object sender, EventArgs e)
        {
            using (new Progress(this, false))
            {
                try
                {
                    Bitmap bitmap = controller.GetSelectedAlbumThumbnail();
                    pbPreview.Image = bitmap;
                    pbPreview.Tag = controller.GetSelectedAlbumUri();
                }
                catch (Exception ex)
                {
                    Output.AppendLine(ex.Message);
                    pbPreview.Image = null;
                    pbPreview.Tag = null;
                }
            }
        }

        private void OnSelectAllAlbumsClick(object sender, EventArgs e)
        {
            for (int i = 0; i < clbAlbums.Items.Count; i++)
            {
                clbAlbums.SetItemChecked(i, true);
            }
            clbAlbums.Update();
        }

        private void OnDeselectAllAlbumsClick(object sender, EventArgs e)
        {
            for (int i = 0; i < clbAlbums.Items.Count; i++)
            {
                clbAlbums.SetItemChecked(i, false);
            }
            clbAlbums.Update();
        }

        private void OnDownloadSelectedAlbumsClick(object sender, EventArgs e)
        {
            Output.Clear();
            if (albums == null)
            {
                Output.AppendLine("No albums.");
                return;
            }
            if (SelectedAlbums.Count == 0)
            {
                Output.AppendLine("No selected albums.");
                return;
            }
            try
            {
                btnCancel.Visible = true;
                using (new Progress(this))
                {
                    using (var dialog = new FolderBrowserDialog())
                    {
                        if (!string.IsNullOrEmpty(OutputDir))
                        {
                            dialog.SelectedPath = OutputDir;
                        }
                        if (dialog.ShowDialog() != DialogResult.OK)
                        {
                            return;
                        }
                        try
                        {
                            OutputDir = dialog.SelectedPath;
                            controller.DownloadSelectedAlbums();
                            Output.AppendLine("Done.");
                        }
                        catch (InvalidDirException ex)
                        {
                            Output.AppendLine(ex.Message);
                            return;
                        }
                    }
                }
            }
            finally
            {
                btnCancel.Visible = false;
            }
        }

        private void OnCancelClick(object sender, EventArgs e)
        {
            needCancel = true;
        }

        private void OnAlbumPreviewClick(object sender, EventArgs e)
        {
            controller.WebOpenSelectedAlbum();
            /*if (pbPreview.Tag != null)
            {
                var process = new Process();
                process.StartInfo = new ProcessStartInfo(pbPreview.Tag.ToString());
                process.Start();
            }*/
        }

        private void OnAlbumsDoubleClick(object sender, EventArgs e)
        {
            controller.WebOpenSelectedAlbum();
        }

        private void OnWebOpenClick(object sender, EventArgs e)
        {
            controller.WebOpenSelectedAlbum();
        }
    }
}